1 00:00:00,860 --> 00:00:01,850 Welcome back. 2 00:00:01,850 --> 00:00:06,800 In this lecture we're going to finally start utilizing the OOP concepts we've just learned about. 3 00:00:06,800 --> 00:00:07,760 In this lecture. 4 00:00:07,760 --> 00:00:13,280 We're going to create this toxic gas cloud here I'll demonstrate it for you real quick. 5 00:00:13,840 --> 00:00:18,370 And when we go to enter this toxic gas cloud, as you can see, it starts damaging us. 6 00:00:18,370 --> 00:00:19,720 And when we leave it, it stops. 7 00:00:19,720 --> 00:00:22,690 And when we go back in, it damages us again. 8 00:00:23,200 --> 00:00:28,270 We're going to be utilizing encapsulation and abstraction in this lecture, as well as learning about 9 00:00:28,270 --> 00:00:31,030 a function in the workspace called git parts and part. 10 00:00:31,060 --> 00:00:33,670 So without further ado, let's get started. 11 00:00:34,150 --> 00:00:38,470 So the first thing you'll want to do is you'll want to grab this model that I've attached to the lecture. 12 00:00:38,470 --> 00:00:44,500 And it's just a part that has a particle emitter and a properties module script inside of it. 13 00:00:44,590 --> 00:00:49,450 So this is the particle emitter that will emit the smoke of our toxic gas cloud. 14 00:00:49,570 --> 00:00:56,320 And inside of the properties module script here, it just lays out how much damage that this gas cloud 15 00:00:56,320 --> 00:00:58,510 will deal per this tick rate. 16 00:00:58,510 --> 00:01:03,070 So it'll deal 15 damage every 0.5 seconds. 17 00:01:03,930 --> 00:01:07,500 I've placed this gas cloud in a folder called gas clouds. 18 00:01:07,500 --> 00:01:09,810 That way my workspace is more organized. 19 00:01:09,810 --> 00:01:14,550 But in the next lecture we'll learn about the collection service so you don't have to keep related things 20 00:01:14,550 --> 00:01:16,440 in your game all in the same folder. 21 00:01:17,100 --> 00:01:20,880 So let's get started creating the class for our toxic gas cloud. 22 00:01:20,910 --> 00:01:24,660 I have this module script here and it's going to be acting as my class. 23 00:01:24,660 --> 00:01:25,230 Now. 24 00:01:25,230 --> 00:01:31,350 Firstly, to uphold the principle of encapsulation, we have to have two tables in our class, one that's 25 00:01:31,350 --> 00:01:35,490 going to store the constructor, while the other is going to be the meta table holding the functions 26 00:01:35,490 --> 00:01:38,010 that will be used on the objects themselves. 27 00:01:38,010 --> 00:01:42,360 This way we can correctly encapsulate the functions to their correct tables. 28 00:01:43,480 --> 00:01:47,080 So in this section here it's going to be for my variables. 29 00:01:49,650 --> 00:01:54,270 And I'm going to create a table for my gas cloud class. 30 00:01:54,390 --> 00:01:58,800 And then I'm also going to create a meta table for the gas cloud class. 31 00:02:00,220 --> 00:02:05,500 And I want my gas cloud to have some basic properties, such as the part that is representing the gas 32 00:02:05,500 --> 00:02:06,130 cloud. 33 00:02:06,130 --> 00:02:07,060 We'll set it to no. 34 00:02:07,060 --> 00:02:11,560 For now, we'll want to have a reference to the particle emitter that's in the gas cloud. 35 00:02:12,070 --> 00:02:15,280 We'll want to know whether or not this gas cloud is enabled. 36 00:02:15,280 --> 00:02:17,560 So we'll set this to false by default. 37 00:02:17,920 --> 00:02:21,370 And then we want access to the properties that are inside of our gas cloud. 38 00:02:21,370 --> 00:02:24,850 And we're going to set the properties to nil for now as well. 39 00:02:25,300 --> 00:02:31,990 We're also going to make sure to set the gas clouds underscore underscore index meta method to itself. 40 00:02:34,620 --> 00:02:36,540 And I'm also going to create another table. 41 00:02:36,540 --> 00:02:39,330 I'll call it current gas clouds. 42 00:02:39,330 --> 00:02:42,960 And it's just going to represent all the objects that I have in my game. 43 00:02:42,960 --> 00:02:45,990 So any gas clouds I have will be stored in here. 44 00:02:45,990 --> 00:02:47,970 All of the tables will be stored in this one. 45 00:02:49,590 --> 00:02:56,130 Next, we're going to need some private functions for our toxic gas cloud class. 46 00:02:56,740 --> 00:02:58,750 And these are going to be private functions. 47 00:02:58,750 --> 00:03:04,360 So we uphold abstraction, meaning we're hiding away details from people that are requiring or using 48 00:03:04,360 --> 00:03:07,240 this class one function we'll need. 49 00:03:07,860 --> 00:03:13,710 Is to get all of the humanoids that are going to be inside of this part. 50 00:03:13,710 --> 00:03:18,090 So whenever a player is going to be inside of this part, we'll use a function to check for all the 51 00:03:18,090 --> 00:03:19,110 parts in this part. 52 00:03:19,110 --> 00:03:23,910 And then we're going to get all the humanoids of each character or player that's inside of this toxic 53 00:03:23,910 --> 00:03:26,190 gas cloud, and damage them accordingly. 54 00:03:26,880 --> 00:03:32,370 So we'll call this function get humanoids and part and we'll pass a part to this function. 55 00:03:32,370 --> 00:03:34,080 We'll leave it empty for now. 56 00:03:34,110 --> 00:03:40,830 We'll also need a function to run the damaging tick while the toxic gas cloud is active. 57 00:03:40,830 --> 00:03:43,320 So we can call it damage tick. 58 00:03:43,320 --> 00:03:48,810 And we'll be passing um, we'll pass self to this, which is going to represent the object. 59 00:03:49,370 --> 00:03:55,940 And in here we'll run a loop in a separate thread using task dot spawn to repeatedly damage and check 60 00:03:55,940 --> 00:04:01,730 for any humanoids within the gas cloud every, uh, however long the tick rate is. 61 00:04:02,610 --> 00:04:07,500 Otherwise, this section is going to store all my public functions, such as my constructor and all 62 00:04:07,500 --> 00:04:10,260 the functions that can be called on the gas clouds. 63 00:04:10,260 --> 00:04:13,440 So we can call this one gas cloud dot new. 64 00:04:14,360 --> 00:04:20,360 And this constructor, remember, has to belong to this gas cloud cable, not to our gas cloud meta 65 00:04:20,360 --> 00:04:20,990 table. 66 00:04:21,610 --> 00:04:27,430 And what we need to pass here, I would say, is just the gas part or the part that's going to be representing 67 00:04:27,430 --> 00:04:28,510 our gas cloud. 68 00:04:28,690 --> 00:04:31,720 And then from that point in here, we could create a table. 69 00:04:31,720 --> 00:04:37,900 We'll call it self equal to set meta table, create a new table and attach the gas cloud meta table 70 00:04:37,900 --> 00:04:38,470 to it. 71 00:04:39,040 --> 00:04:44,110 And then from that point, we can access all of these default properties and override them to whatever 72 00:04:44,110 --> 00:04:45,340 this object is going to be. 73 00:04:45,340 --> 00:04:48,130 So the part is going to be this gas part. 74 00:04:48,900 --> 00:04:56,460 The emitter is going to be equal to the gas part, and we're going to get or we're going to find first 75 00:04:56,460 --> 00:05:01,140 child, which is a particle emitter. 76 00:05:01,710 --> 00:05:06,090 That way we can name the particle emitter whatever we'd like, but we can still get it because it's 77 00:05:06,090 --> 00:05:08,010 part of the particle emitter class. 78 00:05:09,840 --> 00:05:12,960 Set enabled to false. 79 00:05:12,960 --> 00:05:16,590 Actually, it's already set to false by default, so we don't have to set it here. 80 00:05:16,590 --> 00:05:19,440 But we can do properties equal to require. 81 00:05:20,320 --> 00:05:23,050 Gas part properties. 82 00:05:23,470 --> 00:05:27,580 So we're grabbing the properties table and storing it here in this property. 83 00:05:28,610 --> 00:05:34,310 From that point, we can keep track of this object by inserting it inside of our current gas clouds 84 00:05:34,310 --> 00:05:35,030 table. 85 00:05:35,060 --> 00:05:40,340 That way, let's say for some reason, we need a function to get all of the current gas clouds. 86 00:05:40,340 --> 00:05:41,300 We can do so. 87 00:05:41,570 --> 00:05:43,760 So we're going to insert it into this. 88 00:05:44,270 --> 00:05:45,290 Table. 89 00:05:45,740 --> 00:05:50,420 And then once that's done, we can just return this table back to where this function was called. 90 00:05:50,630 --> 00:05:55,070 And in fact, let's make another function inside of the gas cloud table. 91 00:05:55,100 --> 00:05:58,490 I'm going to call it get gas clouds. 92 00:05:58,490 --> 00:06:01,880 And it's just going to return the current gas clouds table. 93 00:06:01,880 --> 00:06:06,740 So if at any time when I'm using this class, I want to get all of the gas clouds that are currently 94 00:06:06,740 --> 00:06:12,590 in my game and be able to enable and disable ones I want, then this will allow me to do so. 95 00:06:14,090 --> 00:06:18,050 Otherwise, we're going to need some functions that are going to belong to our meta table. 96 00:06:18,050 --> 00:06:22,310 And these functions are going to be called directly on these objects themselves. 97 00:06:22,310 --> 00:06:27,170 So one function would be like gas cloud meta table. 98 00:06:27,650 --> 00:06:32,150 Uh, we could do enable to enable the gas cloud because they're not enabled by default. 99 00:06:32,150 --> 00:06:33,800 And this one can be pretty simple. 100 00:06:33,800 --> 00:06:37,460 We can first check if self dot enabled is true. 101 00:06:37,460 --> 00:06:39,050 If it is we'll just return. 102 00:06:40,290 --> 00:06:42,810 Otherwise we can set self dot enable to true. 103 00:06:43,520 --> 00:06:45,590 We can set the emitter. 104 00:06:46,550 --> 00:06:47,360 To true. 105 00:06:47,360 --> 00:06:49,220 So it's emitting particles. 106 00:06:49,220 --> 00:06:52,820 And then we can call that damaged tick function passed self to it. 107 00:06:52,820 --> 00:06:57,590 So that way the gas cloud starts checking for when any players enter inside of it. 108 00:06:58,340 --> 00:07:02,180 And then we could do the same thing for disabling the gas cloud. 109 00:07:04,770 --> 00:07:06,000 Call it disable. 110 00:07:07,120 --> 00:07:14,860 And again we'll check if the object is already disabled, then we'll just return. 111 00:07:15,700 --> 00:07:21,370 Otherwise we'll set enable to false and disable the emitter. 112 00:07:23,660 --> 00:07:25,130 And that seems pretty good. 113 00:07:25,160 --> 00:07:31,970 Then down here we can just have a section called main and we're just going to return. 114 00:07:32,770 --> 00:07:34,750 The gas cloud table. 115 00:07:35,500 --> 00:07:40,060 Now let's go ahead and fill out our damage tick and get humanoids in part function. 116 00:07:40,210 --> 00:07:48,460 So for the damage tick function, what I want to do is I want to use the task dot spawn function to 117 00:07:48,460 --> 00:07:50,920 spawn a new thread. 118 00:07:51,220 --> 00:07:54,940 And what I'll do in here is I'm going to loop constantly. 119 00:07:54,940 --> 00:07:57,760 So while self dot enabled. 120 00:07:57,760 --> 00:08:01,510 So while this gas cloud is enabled what we're going to do. 121 00:08:02,420 --> 00:08:09,110 Is we're going to check for any humanoids in the gas cloud so we can do local humanoids equal to the 122 00:08:09,110 --> 00:08:11,180 get humanoids in part. 123 00:08:11,240 --> 00:08:16,520 So with this function, we can return a table back here that stores all of the humanoids that are inside 124 00:08:16,520 --> 00:08:17,420 of the gas cloud. 125 00:08:17,420 --> 00:08:19,520 So let's fill out that function real quick. 126 00:08:19,760 --> 00:08:24,860 I'll pass the self dot part to this function. 127 00:08:25,310 --> 00:08:27,500 And then inside of this function what we'll do. 128 00:08:28,350 --> 00:08:34,440 Is we can get all the parts that are inside of this part using a function in the workspace called git 129 00:08:34,440 --> 00:08:41,220 parts and part, and it returns an array of parts whose occupied space is shared with the given part, 130 00:08:41,220 --> 00:08:44,400 and we'll pass the part that is passed to the function. 131 00:08:45,220 --> 00:08:51,490 And then we can create a table to store all the humanoids that we find inside of this part. 132 00:08:52,280 --> 00:08:57,860 So what I can do is loop through every single part that is in I pairs parts. 133 00:09:01,160 --> 00:09:03,110 And actually I'll just call this P. 134 00:09:03,110 --> 00:09:06,620 That way we don't confuse it with this part variable up here. 135 00:09:06,860 --> 00:09:10,040 We can check, um, if there's a humanoid. 136 00:09:10,040 --> 00:09:11,810 So we'll make a variable called humanoid. 137 00:09:11,810 --> 00:09:14,720 And we'll set it equal to the part dot parent. 138 00:09:14,720 --> 00:09:17,840 And then we can find first child which is a humanoid. 139 00:09:17,960 --> 00:09:23,660 So if this part is a torso, a head or whatever, the parent should be the player's character and the 140 00:09:23,660 --> 00:09:25,910 character should have a child that is a humanoid. 141 00:09:26,360 --> 00:09:31,130 However, if there is no humanoid, then we can just return because we don't care about this part. 142 00:09:32,150 --> 00:09:36,500 Otherwise, if there is a humanoid, then we also need to make sure that this humanoid isn't already 143 00:09:36,500 --> 00:09:42,500 stored within the humanoids table, because there's going to be multiple parts of a player inside of 144 00:09:42,500 --> 00:09:45,260 our part, like each limb, the head. 145 00:09:45,260 --> 00:09:50,060 And this will run multiple times, and it might store that player's humanoid multiple times, which 146 00:09:50,060 --> 00:09:51,140 we don't want to happen. 147 00:09:51,140 --> 00:09:58,190 So we can use table, dot, find and check to see if this humanoid already exists within the humanoid 148 00:09:58,220 --> 00:09:59,030 table. 149 00:09:59,150 --> 00:10:02,450 If it does, then we're just going to continue looping. 150 00:10:02,450 --> 00:10:05,030 And actually right here we don't want to return. 151 00:10:05,030 --> 00:10:08,240 We want to continue looping through all of the parts. 152 00:10:08,240 --> 00:10:12,620 If we return, it's going to exit out of this for loop prematurely, and we won't be able to check all 153 00:10:12,620 --> 00:10:13,220 the parts. 154 00:10:13,220 --> 00:10:15,860 So we're going to do continue and not return. 155 00:10:16,340 --> 00:10:23,360 Otherwise, if it matches all the criteria, then we can insert this humanoid into the humanoids table. 156 00:10:25,510 --> 00:10:30,760 And then at the very end of this function, we're going to return humanoids. 157 00:10:31,120 --> 00:10:31,570 Great. 158 00:10:31,570 --> 00:10:36,220 So now we have the humanoids table, all the humanoids that are inside of our gas cloud. 159 00:10:36,520 --> 00:10:39,760 What we could do is loop through each one of those humanoid. 160 00:10:43,530 --> 00:10:48,330 And we can use a function on the humanoid called take damage. 161 00:10:48,330 --> 00:10:56,910 And the amount of damage we want to take is the self dot properties dot and it's called damage per tick. 162 00:10:58,270 --> 00:11:05,350 And then at the very end of this while loop, we can wait for the self dot properties dot tick rate. 163 00:11:05,920 --> 00:11:07,870 So currently it's at 0.5. 164 00:11:07,870 --> 00:11:10,300 So this loop is going to run every 0.5 seconds. 165 00:11:10,300 --> 00:11:17,200 And it's going to damage each player by the damage per tick which I believe was yeah 15. 166 00:11:17,930 --> 00:11:20,720 So now I think this class is pretty good. 167 00:11:20,750 --> 00:11:25,490 We've encapsulated the functions to belong to two different tables. 168 00:11:25,490 --> 00:11:31,220 So that way we can't use the constructor from the objects themselves because they have a different meta 169 00:11:31,220 --> 00:11:32,600 table attached to them. 170 00:11:33,020 --> 00:11:38,480 And we've also upheld the principle of abstraction by hiding the internal workings of our class to these 171 00:11:38,480 --> 00:11:43,970 local functions, because we don't want to store them in the table, because anybody using this module 172 00:11:43,970 --> 00:11:46,310 script doesn't need to see these functions in the first place. 173 00:11:46,700 --> 00:11:49,490 We've also kept this table here hidden as well. 174 00:11:49,490 --> 00:11:55,070 And if anybody wants to access to this table, they have to call a function called get gas clouds. 175 00:11:55,710 --> 00:12:01,140 So again we are encapsulating and we are abstracting our code here. 176 00:12:01,170 --> 00:12:06,690 Now I have another script that I made, and this script is going to require this module script and go 177 00:12:06,690 --> 00:12:10,830 through every single gas cloud that I have in this folder and create new objects for each. 178 00:12:10,830 --> 00:12:13,590 And I'm going to enable all of these gas clouds. 179 00:12:13,590 --> 00:12:21,060 So what we need to do is we need to get a service depending on where you stored your toxic gas cloud 180 00:12:21,060 --> 00:12:21,690 module script. 181 00:12:21,690 --> 00:12:23,400 But mine stored in server storage. 182 00:12:23,400 --> 00:12:25,860 So I'm going to get it from server storage. 183 00:12:29,950 --> 00:12:32,650 And then we can have a section here for variables. 184 00:12:36,300 --> 00:12:40,290 So I'm going to get the glass cloud class. 185 00:12:40,290 --> 00:12:42,510 I'm going to require it from server storage. 186 00:12:42,510 --> 00:12:47,700 I have a folder called classes and it's in there called Toxic Gas Cloud. 187 00:12:48,180 --> 00:12:50,130 So now I have required my module script. 188 00:12:50,130 --> 00:12:52,410 And that means all the code in it has ran. 189 00:12:53,130 --> 00:12:57,960 And now I can also reference the folder where all the gas clouds will be. 190 00:12:57,960 --> 00:13:01,890 I'll call it gas clouds and it's equal to workspace dot gas clouds. 191 00:13:03,450 --> 00:13:08,850 From this point I can have a section called main, because what I'm going to do is I'm going to loop 192 00:13:08,850 --> 00:13:13,620 through every single gas cloud that is in the gas clouds folder. 193 00:13:13,620 --> 00:13:16,080 So gas clouds get children. 194 00:13:17,560 --> 00:13:25,270 What we'll do is we'll use the gas cloud class and create a new gas cloud and pass this part to it. 195 00:13:26,640 --> 00:13:33,060 And then once that's done and this function returns back to me the table or object that represents this 196 00:13:33,060 --> 00:13:35,970 gas cloud, I can call the enable function on it. 197 00:13:35,970 --> 00:13:38,160 So I enable this gas cloud. 198 00:13:38,580 --> 00:13:44,130 So that means if I go and run my game this part should start emitting particles. 199 00:13:44,680 --> 00:13:45,760 And there we go. 200 00:13:46,270 --> 00:13:50,320 Our gas cloud looks to be working and it's emitting all of the particles. 201 00:13:50,770 --> 00:13:54,160 So let's actually go ahead and click play here. 202 00:13:56,970 --> 00:14:01,860 And we should be able to go inside of our gas cloud and start having damage dealt to us. 203 00:14:02,220 --> 00:14:03,090 So there we go. 204 00:14:03,120 --> 00:14:08,310 We're losing damage every 0.5 seconds and it's 15 damage per tick. 205 00:14:08,310 --> 00:14:09,360 So very nice. 206 00:14:11,170 --> 00:14:17,650 And now because I've implemented that get gas clouds function, what I could do is I could wait 10s 207 00:14:17,650 --> 00:14:18,190 here. 208 00:14:19,340 --> 00:14:24,110 And then I could get every single gas cloud that is in my game, so I could loop through every single 209 00:14:24,110 --> 00:14:26,660 gas cloud and I pairs. 210 00:14:26,660 --> 00:14:32,150 We're going to reference the gas cloud class and get every single gas cloud. 211 00:14:32,570 --> 00:14:37,280 And then what I could do with that is I could disable this gas cloud. 212 00:14:37,280 --> 00:14:38,390 Disable. 213 00:14:39,720 --> 00:14:44,790 And now that means after 10s, every single gas cloud in my game should be disabled. 214 00:14:44,820 --> 00:14:50,670 So let's go ahead and actually duplicate this gas cloud multiple times because I can have multiple objects. 215 00:14:51,620 --> 00:14:53,960 And we can go and play test the game here. 216 00:14:54,970 --> 00:14:58,960 And we've got our gas clouds running and we're taking damage. 217 00:14:58,960 --> 00:15:00,040 Still perfect. 218 00:15:05,570 --> 00:15:08,390 Oh, looks like we're not taking damage within this one. 219 00:15:08,390 --> 00:15:12,260 And, oh, it looks like the gas clouds have been disabled. 220 00:15:12,260 --> 00:15:13,190 And that's why. 221 00:15:13,970 --> 00:15:14,480 There we go. 222 00:15:14,480 --> 00:15:18,170 The gas clouds have been disabled and we no longer take any damage. 223 00:15:18,800 --> 00:15:20,960 Um, let's make sure all of that is working. 224 00:15:20,960 --> 00:15:22,520 So I'm going to play again. 225 00:15:24,340 --> 00:15:29,020 So let me go in this one, okay, I take damage, I go in this one. 226 00:15:29,020 --> 00:15:29,590 Perfect. 227 00:15:29,590 --> 00:15:30,700 Take damage. 228 00:15:30,700 --> 00:15:33,520 And a few more seconds they should disable. 229 00:15:34,860 --> 00:15:35,250 There we go. 230 00:15:35,250 --> 00:15:39,060 No more particles and we do not take any more damage. 231 00:15:40,040 --> 00:15:44,570 As you can see, this is an example of how we can use module scripts in object oriented programming 232 00:15:44,600 --> 00:15:49,790 to create scalable and maintainable code for things in our game, like toxic gas clouds. 233 00:15:49,820 --> 00:15:51,110 I hope you learned a lot. 234 00:15:51,110 --> 00:15:55,490 And in the next lecture, we're going to be learning about how to use composition and the collection 235 00:15:55,490 --> 00:15:57,590 service to create land mines. 236 00:15:57,590 --> 00:15:59,000 So I'll see you there.